package com.qdaily.supportlibrary.util;

import android.content.Context;
import android.text.TextUtils;
import com.qdaily.supportlibrary.request.*;
import in.srain.cube.util.CLog;

import java.io.File;
import java.util.Map;

/**
 * framework
 *
 * @author chencheng
 * @version 1.0
 * @time Mar 31, 20154:34:46 PM
 * @contact lovejiuwei@gmail.com
 */
public class NetUtil {

    private static NetUtil mNetUtil;

    private Context mContext;

    private NetDataCallBack mNetDataCallBack;

    private final String LOG_TAG = "NetUtil";

    /**
     * 在工程的assets目录下，切记勿删除。
     */
    private final String CACHE_GET_ASSETS_PATH = "request_init/get_cache_data_list.json";

    private final String CACHE_POST_ASSETS_PATH = "request_init/post_cache_data_list.json";

    private NetUtil(Context context) {
        this.mContext = context;
    }

    public static NetUtil getInstance(Context context) {
        if (mNetUtil == null) {
            mNetUtil = new NetUtil(context);
        }
        return mNetUtil;
    }

    /**
     * 网络回调基类
     */
    public interface NetDataCallBack {
        void onRequestFinish(NetParams netParams, JsonData data);

        void onRequestFail(NetParams netParams, FailData failData);
    }

    /**
     * 网络回调扩展类，用于缓存的回调。有点耦合。先这么办吧。操。
     * <p/>
     * 数据加载完回调。这个是开发人员最常关心的一个回调。
     * public void onCacheAbleRequestFinish(data, resultType, outOfDate);
     * 缓存数据加载完回调
     * public void onCacheData(data, outOfDate);
     * 服务器数据加载完回调
     * public void onRequestFinish(data);
     * 数据加载失败回调
     * public void onRequestFail(failData)
     */
    public interface CacheNetDataCallBack extends NetDataCallBack {
        void onRequestFinish(NetParams netParams, JsonData data, CacheAbleRequest.ResultType type, boolean outOfDate);

        void onCacheResponse(NetParams netParams, JsonData data);
    }

    /**
     * 请求参数基类
     */
    public interface NetParams {
        Map<String, Object> getPostNetParams();

        Map<String, Object> getHeaderNetParams();

        String getUrl();
    }

    /**
     * 请求参数扩展类，主要用于上传头像
     */
    public interface NetParamsWithUpload extends NetParams {
        String getUploadFieldName();

        File getUploadFile();
    }

    public void doPost(final NetParams netParams, final NetDataCallBack netDataCallBack) {
        if (null == netParams ||
                netParams.getPostNetParams() == null ||
                netParams.getPostNetParams().size() == 0 ||
                null == netDataCallBack) {
            CLog.d(LOG_TAG, "the doPost is broken");
            netDataCallBack.onRequestFail(netParams, FailData.inputError(null));
            return;
        }

        RequestHandler<JsonData> requestHandler = new RequestHandler<JsonData>() {
            @Override
            public JsonData processOriginData(JsonData jsonData) {
                return jsonData;
            }

            @Override
            public void onRequestFail(FailData failData) {
                netDataCallBack.onRequestFail(netParams, failData);
            }

            @Override
            public void onRequestFinish(JsonData data) {
                if (!data.isNull()) {
                    netDataCallBack.onRequestFinish(netParams, data);
                } else {
                    netDataCallBack.onRequestFail(netParams, FailData.networkError(null));
                }
            }
        };

        SimpleRequest<JsonData> request = new SimpleRequest<JsonData>(requestHandler);
        RequestData requestData = request.getRequestData();
        requestData.usePost(true);
        requestData.setRequestUrl(netParams.getUrl());
        requestData.addPostData(netParams.getPostNetParams());
        if (netParams.getHeaderNetParams() != null && netParams.getHeaderNetParams().size() > 0) {
            requestData.addHeader(netParams.getHeaderNetParams());
        }
        request.send();
    }

    public void doPost(final NetParamsWithUpload netParams, final NetDataCallBack netDataCallBack) {
        if (null == netParams ||
                netParams.getPostNetParams() == null ||
                netParams.getPostNetParams().size() == 0 ||
                null == netDataCallBack) {
            CLog.d(LOG_TAG, "the doPost is broken");
            netDataCallBack.onRequestFail(netParams, FailData.inputError(null));
            return;
        }

        RequestHandler<JsonData> requestHandler = new RequestHandler<JsonData>() {
            @Override
            public JsonData processOriginData(JsonData jsonData) {
                return jsonData;
            }

            @Override
            public void onRequestFail(FailData failData) {
                netDataCallBack.onRequestFail(netParams, failData);
            }

            @Override
            public void onRequestFinish(JsonData data) {
                if (!data.isNull()) {
                    netDataCallBack.onRequestFinish(netParams, data);
                } else {
                    netDataCallBack.onRequestFail(netParams, FailData.networkError(null));
                }
            }
        };

        SimpleRequest<JsonData> request = new SimpleRequest<JsonData>(requestHandler);
        RequestData requestData = request.getRequestData();
        requestData.usePost(true);
        requestData.setRequestUrl(netParams.getUrl());
        requestData.addPostData(netParams.getPostNetParams());
        if (netParams.getUploadFile() != null && netParams.getUploadFieldName() != null)
        {
            requestData.addFile(netParams.getUploadFieldName(), netParams.getUploadFile());
        }
        if (netParams.getHeaderNetParams() != null && netParams.getHeaderNetParams().size() > 0) {
            requestData.addHeader(netParams.getHeaderNetParams());
        }
        request.send();
    }

    public void doGet(final NetParams netParams, final NetDataCallBack netDataCallBack) {
        if (null == netParams || null == netDataCallBack) {
            CLog.d(LOG_TAG, "the doGet is broken");
            netDataCallBack.onRequestFail(netParams, FailData.inputError(null));
            return;
        }

        RequestHandler<JsonData> requestHandler = new RequestHandler<JsonData>() {
            @Override
            public JsonData processOriginData(JsonData jsonData) {
                return jsonData;
            }

            @Override
            public void onRequestFail(FailData failData) {
                netDataCallBack.onRequestFail(netParams, failData);
            }

            @Override
            public void onRequestFinish(JsonData data) {
                if (!data.isNull()) {
                    netDataCallBack.onRequestFinish(netParams, data);
                } else {
                    netDataCallBack.onRequestFail(netParams, FailData.networkError(null));
                }
            }
        };

        SimpleRequest<JsonData> request = new SimpleRequest<JsonData>(requestHandler);
        RequestData requestData = request.getRequestData();
        requestData.setRequestUrl(netParams.getUrl());
        if (netParams.getPostNetParams() != null && netParams.getPostNetParams().size() > 0) {
            requestData.addQueryData(netParams.getPostNetParams());
        }
        if (netParams.getHeaderNetParams() != null && netParams.getHeaderNetParams().size() > 0) {
            requestData.addHeader(netParams.getHeaderNetParams());
        }
        request.send();
    }

    public void doGetWithCache(final NetParams netParams, final CacheNetDataCallBack netDataCallBack) {
        if (null == netParams || null == netDataCallBack) {
            CLog.d(LOG_TAG, "the doGetWithCache is broken");
            netDataCallBack.onRequestFail(netParams, FailData.inputError(null));
            return;
        }

        CacheAbleRequestHandler<JsonData> requestHandler = new CacheAbleRequestDefaultHandler<JsonData>() {
            @Override
            public void onRequestFail(FailData failData) {
                super.onRequestFail(failData);
                netDataCallBack.onRequestFail(netParams, failData);
            }

            @Override
            public void onCacheData(JsonData data, boolean outOfDate) {
                CLog.d(LOG_TAG, "[onCacheData]outOfDate=" + outOfDate + ", data=" + data.toString());
                if (!TextUtils.isEmpty(data.toString()))
                {
                    netDataCallBack.onCacheResponse(netParams, data);
                }
            }

            @Override
            public void onCacheAbleRequestFinish(JsonData data, CacheAbleRequest.ResultType type, boolean outOfDate) {
                if (!data.isNull()) {
                    netDataCallBack.onRequestFinish(netParams, data, type, outOfDate);
                } else {
                    netDataCallBack.onRequestFail(netParams, FailData.networkError(null));
                }
            }

            @Override
            public JsonData processOriginData(JsonData jsonData) {
                return jsonData;
            }
        };

        CacheAbleRequest<JsonData> request = new CacheAbleRequest<JsonData>(requestHandler);
        request.setTimeout(8000);
        //        request.setCacheTime( Integer.MAX_VALUE );
        if (netParams.getPostNetParams() != null && netParams.getPostNetParams().size() > 0) {
            request.getRequestData().addQueryData(netParams.getPostNetParams());
        }
        if (netParams.getHeaderNetParams() != null && netParams.getHeaderNetParams().size() > 0) {
            request.getRequestData().addHeader(netParams.getHeaderNetParams());
        }
        request.getRequestData().setRequestUrl(netParams.getUrl());
        request.setAssertInitDataPath(CACHE_GET_ASSETS_PATH);
        request.setCacheKey("qdaily-cache-get-" + netParams.getUrl());
        request.send();
    }

    public void doPostWithCache(final NetParams netParams, final CacheNetDataCallBack netDataCallBack) {
        if (null == netParams || null == netDataCallBack) {
            CLog.d(LOG_TAG, "the doGetWithCache is broken");
            netDataCallBack.onRequestFail(netParams, FailData.inputError(null));
            return;
        }

        CacheAbleRequestHandler<JsonData> requestHandler = new CacheAbleRequestDefaultHandler<JsonData>() {
            @Override
            public void onRequestFail(FailData failData) {
                super.onRequestFail(failData);
                netDataCallBack.onRequestFail(netParams, failData);
            }

            @Override
            public void onCacheAbleRequestFinish(JsonData data, CacheAbleRequest.ResultType type, boolean outOfDate) {
                if (!data.isNull()) {
                    netDataCallBack.onRequestFinish(netParams, data, type, outOfDate);
                } else {
                    netDataCallBack.onRequestFail(netParams, FailData.networkError(null));
                }
            }

            @Override
            public JsonData processOriginData(JsonData jsonData) {
                return jsonData;
            }
        };

        CacheAbleRequest<JsonData> request = new CacheAbleRequest<JsonData>(requestHandler);
        request.setTimeout(8000);
        //        request.setCacheTime( Integer.MAX_VALUE );
        request.getRequestData().usePost(true);
        request.getRequestData().setRequestUrl(netParams.getUrl());
        request.getRequestData().addPostData(netParams.getPostNetParams());
        request.setAssertInitDataPath(CACHE_POST_ASSETS_PATH);
        request.setCacheKey("qdaily-cache-post-" + netParams.getUrl());
        request.send();
    }

    public void doUploadFile(final NetParamsWithUpload netParams, final NetDataCallBack netDataCallBack) {
        if (null == netParams && null == netDataCallBack) {
            CLog.d(LOG_TAG, "the doPost is broken");
            return;
        }

        RequestHandler<JsonData> requestHandler = new RequestHandler<JsonData>() {
            @Override
            public JsonData processOriginData(JsonData jsonData) {
                return jsonData;
            }

            @Override
            public void onRequestFail(FailData failData) {
                netDataCallBack.onRequestFail(netParams, failData);
            }

            @Override
            public void onRequestFinish(JsonData data) {
                if (!data.isNull()) {
                    netDataCallBack.onRequestFinish(netParams, data);
                } else {
                    netDataCallBack.onRequestFail(netParams, FailData.networkError(null));
                }
            }
        };

        final SimpleRequest<JsonData> request = new SimpleRequest<JsonData>();
        request.setRequestHandler(requestHandler);

        RequestData requestData = request.getRequestData();
        requestData.usePost(true);
        if (!TextUtils.isEmpty(netParams.getUploadFieldName()) && null != netParams.getUploadFile()) {
            requestData.addFile(netParams.getUploadFieldName(), netParams.getUploadFile());
        }
        requestData.setRequestUrl(netParams.getUrl());
        requestData.addPostData(netParams.getPostNetParams());
        if (netParams.getHeaderNetParams() != null && netParams.getHeaderNetParams().size() > 0) {
            requestData.addHeader(netParams.getHeaderNetParams());
        }

        request.send();
    }
}
